package com.tbit.uqbike.client.util.H5Login;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.CryptoException;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.SignAlgorithm;

import java.security.*;

/**
 * LySign
 *
 * @date 2021/1/6 11:02
 */
public class LySign {

    /**
     * 算法
     */
    protected String algorithm;

    protected String algorithmAfterWith;
    /**
     * 公钥
     */
    protected PublicKey publicKey;
    /**
     * 私钥
     */
    protected PrivateKey privateKey;

    /**
     * 签名，用于签名和验证
     */
    protected Signature signature;

    /**
     * @param algorithmE
     * @param privateKey
     * @param privateKey
     */
    public LySign(SignAlgorithm algorithmE, byte[] privateKey, byte[] publicKey) {
        this.algorithm = algorithmE.getValue();
        this.algorithmAfterWith = KeyUtil.getAlgorithmAfterWith(this.algorithm);
        this.privateKey = SecureUtil.generatePrivateKey(this.algorithmAfterWith, privateKey);
        this.publicKey = SecureUtil.generatePublicKey(this.algorithmAfterWith, publicKey);
        try {
            this.signature = Signature.getInstance(algorithm);
        } catch (NoSuchAlgorithmException e) {
            throw new CryptoException(e);
        }
    }

    /**
     * @param algorithm
     * @param privateKey
     * @param publicKey
     * @param hexStr     是否16进制 true 是 false base64
     * @return
     */
    public static LySign of(SignAlgorithm algorithm, String privateKey, String publicKey, boolean hexStr) {
        byte[] privateBytes;
        byte[] publicBytes;
        if (hexStr) {
            privateBytes = HexUtil.decodeHex(privateKey);
            publicBytes = HexUtil.decodeHex(publicKey);
        } else {
            privateBytes = Base64.decode(privateKey);
            publicBytes = Base64.decode(publicKey);
        }
        return new LySign(algorithm, privateBytes, publicBytes);
    }

    public String sign(String data) {
        try {
            signature.initSign(privateKey);
            signature.update(data.getBytes());
            byte[] sign = signature.sign();
            return HexUtil.encodeHexStr(sign, false);
        } catch (InvalidKeyException | SignatureException e) {
            throw new CryptoException(e);
        }
    }

    public boolean verify(String data, String sign) {
        try {
            signature.initVerify(publicKey);
            signature.update(data.getBytes());
            return signature.verify(HexUtil.decodeHex(sign));
        } catch (InvalidKeyException | SignatureException e) {
            throw new CryptoException(e);
        }
    }
}
